//
// Created by WangPeng on 2024/8/15.
//

#include "rtp_protocol.h"
#include <arpa/inet.h>
#include <cstring>
#include <iostream>
#include "../socket/udp_sk.h"

CRtpProtocol::CRtpProtocol()
    : CRtpProtocol(0, 0,
                   0, RTP_VERSION,
                   RTP_PAYLOAD_TYPE_H264, 0,
                    0, 0, 0x88923423)
{

}


CRtpProtocol::CRtpProtocol(uint8_t csrc_len, uint8_t extension,
                           uint8_t padding, uint8_t version,
                           uint8_t payload_type, uint8_t marker,
                           uint16_t seq, uint32_t timestamp,
                           uint32_t ssrc)
{
    rtp_header_.csrc_len = csrc_len;
    rtp_header_.extension = extension;
    rtp_header_.padding = padding;
    rtp_header_.version = version;
    rtp_header_.payload_type = payload_type;
    rtp_header_.marker = marker;
    rtp_header_.seq = seq;
    rtp_header_.timestamp = timestamp;
    rtp_header_.ssrc = ssrc;

    //根据MTU构造最大的payload空间
    std::size_t alloc_size = sizeof(struct RtpPacket) + RTP_MAX_PKT_SIZE + RTP_MAX_PKT_SIZE;
    packet_ = static_cast<struct RtpPacket*>(std::malloc(alloc_size));
    if (nullptr == packet_)
    {
        std::cerr << "Memory allocation failed!" << std::endl;
        return;
    }
    //拷贝头部数据
    std::memcpy(&(packet_->hrtp), &rtp_header_, sizeof(struct RtpHeader));
}

CRtpProtocol::~CRtpProtocol()
{
    ::free(packet_);
}

int CRtpProtocol::send_rtp_over_udp(CUdpSocket *udp_socket, struct RtpPacket *rtp_packet, uint32_t frame_size)
{
    rtp_packet->hrtp.seq = htons(rtp_packet->hrtp.seq);//从主机字节顺序转变成网络字节顺序
    rtp_packet->hrtp.timestamp = htonl(rtp_packet->hrtp.timestamp);
    rtp_packet->hrtp.ssrc = htonl(rtp_packet->hrtp.ssrc);

    ssize_t ret = udp_socket->send_udp_package(rtp_packet, frame_size + RTP_HEADER_SIZE);

    rtp_packet->hrtp.seq = ntohs(rtp_packet->hrtp.seq);
    rtp_packet->hrtp.timestamp = ntohl(rtp_packet->hrtp.timestamp);
    rtp_packet->hrtp.ssrc = ntohl(rtp_packet->hrtp.ssrc);

    return static_cast<int>(ret);
}
